/*--------------------------------------------------------------------------
        File Name	: m_ota.h
        Author		: liu
        Description	: 固件升级
--------------------------------------------------------------------------*/

#ifndef M_OTA_H
#define M_OTA_H

#include <stdint.h>

//------------------------------OTA FLASH 注意NRF52 pagesize=4K ---------------------

#define M_OTA_SOFTDEVICE_SIZE (112 * 1024) //协议栈大小
#define M_OTA_BOOTLOADER_SIZE (20 * 1024)  // bootloader大小
#define M_OTA_FLASH_DATA_SIZE (20 * 1024)  // FLASH作为数据存储区大小

#define M_OTA_APP_MAX_SIZE ((512 * 1024 - M_OTA_SOFTDEVICE_SIZE - M_OTA_BOOTLOADER_SIZE - M_OTA_FLASH_DATA_SIZE) / 2) // APP区FLASH最大值

#if (((M_OTA_APP_MAX_SIZE / 1024) & 3) != 0)
#error "OTA FLASH DEFINE ERROR!!!"
#endif

#define M_OTA_APP_START_ADDRESS (M_OTA_SOFTDEVICE_SIZE)
#define M_OTA_SWAP_START_ADDRESS (M_OTA_APP_START_ADDRESS + M_OTA_APP_MAX_SIZE)
#define M_OTA_BOOTLOADER_START_ADDRESS (512 * 1024 - M_OTA_BOOTLOADER_SIZE)

#define M_OTA_PACKET_SIZE_MAX (1024 + 512)

#define M_OTA_EXTERN_FLASH_SIZE (400 * 1024)

//#define     M_OTA_EXTERN_FLASH_START_ADDR   (6*1024*1024-M_OTA_EXTERN_FLASH_SIZE) //6M预留400K给OTA

uint32_t get_ota_extern_start_addr(void);
//------------------------------OTA FLASH---------------------------------------------
//升级类型
typedef enum
{
    M_OTA_TYPE_APP = 1,    //升级应用程序
    M_OTA_TYPE_BOOTLOADER, //升级bootloader
    M_OTA_TYPE_SOFTDEVICE, //升级协议栈
} m_ota_type_t;
//状态
typedef enum
{
    M_OTA_STATE_STANBY = 0, //空闲中
    M_OTA_STATE_READY,      //已准备好
    M_OTA_STATE_INIT,       //已初始化
    M_OTA_STATE_PACKET,     //接收包中
    M_OTA_STATE_CHECK,      //校验通过
    M_OTA_STATE_END,        //升级完成
} m_ota_state_t;

//指令类型
typedef enum
{
    M_OTA_CMD_START = 1,
    M_OTA_CMD_INIT,
    M_OTA_CMD_PACKET,
    M_OTA_CMD_CHECK,
    M_OTA_CMD_END,
    M_OTA_CMD_ASK,
    // M_OTA_CMD_USER_FLASH_WRITE = 0x10,
    // M_OTA_CMD_RES_INIT = 0x21,
    // M_OTA_CMD_RES_FRAME = 0x22,
    // M_OTA_CMD_RES_CHECK = 0x23,
    // M_OTA_CMD_RES_CLEAR = 0x24,

    //文件传输，外部FLASH
    M_OTA_CMD_FILE_ASK = 0x30,
    M_OTA_CMD_FILE_INIT = 0x31,
    M_OTA_CMD_FILE_PACKET,
    M_OTA_CMD_FILE_CHECK,
    M_OTA_CMD_FILE_DEL,

    //文件传输-读取文件
    M_OTA_CMD_FILE_READ_INIT = 0x3A,
    M_OTA_CMD_FILE_READ_PACKET,
    M_OTA_CMD_FILE_READ_END,

    M_OTA_CMD_SLEEP_DATA_SAVE = 0x3E,
    M_OTA_CMD_READ_TODAY_SLEEP_DATA = 0x3F,

    //运动模式指令
    M_OTA_CMD_DATA_SUMMARY = 0x41,
    M_OTA_CMD_DATA_SUMMARY_RSP = 0x42,
    M_OTA_CMD_DATA_REQUEST = 0x43,
    M_OTA_CMD_DATA_REQUEST_RSP = 0x44,
    M_OTA_CMD_DATA_DETAIL = 0x45,
    M_OTA_CMD_DATA_DETAIL_RSP = 0x46,
#ifdef USE_CT1711
    CMD_TEMPERATURE_REQUESET = 0x50,
    CMD_TEMPERATURE_RESPONSE = 0x51,
    CMD_BODY_TEMPERATURE_REQUESET = 0x52,
    CMD_BODY_TEMPERATURE_RESPONSE = 0x53,
#endif
#ifdef SOCIAL_DISTANCE
    CMD_SOCIAL_DISTANCE_LOG_GET = 0x56,
#endif

    // flash操作指令
    M_OTA_CMD_EXT_FLASH_ERASE = 0x60,
    M_OTA_CMD_EXT_FLASH_WRITE,
    M_OTA_CMD_EXT_FLASH_READ,

    M_OTA_CMD_ECG_LIST_REQUEST = 0x70,
    M_OTA_CMD_ECG_LIST_RESPONSE,
    M_OTA_CMD_ECG_DATA_REQUEST,
    M_OTA_CMD_ECG_DATA_RESPONSE,
} m_ota_cmd_type_t;

//错误码定义
typedef enum
{
    M_OTA_SUCCESS = 0,
    M_OTA_ERROR_SIZE,
    M_OTA_ERROR_DATA,
    M_OTA_ERROR_STATE,
    M_OTA_ERROR_FORMAT,
    M_OTA_ERROR_FLASH_OPERATE,
    M_OTA_ERROR_LOWER_POWER,
    M_OTA_ERROR_CREATE,
    M_OTA_ERROR_OPEN,
    M_OTA_ERROR_CRC_PASS,
    M_OTA_ERROR_UNKNOWN_FILE,
} m_ota_error_code_t;

//指令处理结果回调通道
typedef void (*m_ota_handle_event)(m_ota_cmd_type_t cmd_type, m_ota_error_code_t result);

//升级控制
typedef struct m_ota_s
{
    m_ota_type_t type; //升级类型 1=nrf-app , 2=nrf-boot , 3=nrf-sd
    uint8_t state;     //状态
    uint16_t crc16;
    uint16_t checksum;
    uint16_t packet_sn;
    uint32_t firmware_size;
    uint32_t firmware_received; //已收到的数据
    uint32_t enc_key;
    m_ota_handle_event ack_handle; //指令处理结果回调通道

    uint8_t data_buff[M_OTA_PACKET_SIZE_MAX]; //静态缓存

} m_ota_t;

#define OTA_FILE_MAGIC_NUM (0x81BDC3E5)
typedef struct
{
    uint32_t magic;
    uint32_t code_size_before_compress; //压缩前的大小
    uint32_t code_size_after_compress;  //压缩前的大小
    uint32_t file_check_sum;
    char fw_version[32];
    char hw_version[32];
} ota_file_header_t;

/*--------------------------------------------------------------------
- Function Name:
- param:
- retval:
- Introduction:
----------------------------------------------------------------------*/
uint8_t m_ota_cmd_start(uint8_t *p_data, uint16_t length);
/*--------------------------------------------------------------------
 - Function Name:  void m_ota_module_init(void)
 - param:
 - retval:
 - Introduction: 初始化m_ota模块
 ----------------------------------------------------------------------*/
void m_ota_module_init(m_ota_handle_event ota_ack_handle);

/*--------------------------------------------------------------------
- Function Name:
- param:
- retval:	0=ok
- Introduction: 固件升级初始化
----------------------------------------------------------------------*/
uint8_t m_ota_cmd_init(uint8_t *p_data, uint16_t length);

/*--------------------------------------------------------------------
- Function Name:
- param:
- retval: 0=ok
- Introduction: 接收到数据-存放于swap区域
----------------------------------------------------------------------*/
uint8_t m_ota_cmd_packet(uint8_t *p_data, uint16_t length);

/*--------------------------------------------------------------------
 - Function Name:
 - param:
 - retval:
 - Introduction: 结束固件传输 --> 校验结果
 ----------------------------------------------------------------------*/
uint8_t m_ota_cmd_check(uint8_t *p_data, uint16_t length);

/*--------------------------------------------------------------------
- Function Name:
- param:
- retval:
- Introduction: 结束固件升级
----------------------------------------------------------------------*/
uint8_t m_ota_cmd_end(uint8_t *p_data, uint16_t length);

/*--------------------------------------------------------------------
 - Function Name:
 - param:
 - retval:
 - Introduction: 获取当前升级状态
 ----------------------------------------------------------------------*/
uint8_t m_ota_cmd_ask(uint8_t *p_data, uint16_t length);

/*--------------------------------------------------------------------
- Function Name:
- param:
- retval:
- Introduction:state[1]+received_size[4]
----------------------------------------------------------------------*/
uint8_t m_ota_get_state(uint8_t *p_data);

/*--------------------------------------------------------------------
- Function Name:  void m_ota_stop(void)
- param:
- retval:
- Introduction: 停止ota,断开蓝牙连接时会调用
----------------------------------------------------------------------*/
void m_ota_stop(void);

// uint8_t m_flash_user_write(uint8_t *p_data, uint16_t len);
void m_ota_reset_timer_start(uint32_t delay_ms);
uint8_t *m_ota_get_buf_addr(void);
#endif
